﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MobileServices;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using System.Linq;

// To add offline sync support, add the NuGet package Microsoft.WindowsAzure.MobileServices.SQLiteStore
// to your project. Then, uncomment the lines marked // offline sync
// For more information, see: http://aka.ms/addofflinesync
//using Microsoft.WindowsAzure.MobileServices.SQLiteStore;  // offline sync
//using Microsoft.WindowsAzure.MobileServices.Sync;         // offline sync

namespace TelemetryMobileService
{
    sealed partial class MainPage: Page
    {
        //Note: To change the table from the Azure Mobile Service (ie Same service and therefore same app key) ..
        // Just change the class name in the file using Refactoring
        private MobileServiceCollection<Telemetry2, Telemetry2> telemetryItems;
        private IMobileServiceTable<Telemetry2> telemetryTable = App.MobileService.GetTable<Telemetry2>();
        //private IMobileServiceSyncTable<TodoItem> todoTable = App.MobileService.GetSyncTable<TodoItem>(); // offline sync

        public MainPage()
        {
            this.InitializeComponent();
        }

        private async Task InsertTelemetryItem(Telemetry2 telemetryItem)
        {
            // This code inserts a new TodoItem into the database. When the operation completes
            // and Mobile Services has assigned an Id, the item is added to the CollectionView
            await telemetryTable.InsertAsync(telemetryItem);
            //telemetryItems.Add(telemetryItem);
            await RefreshTelemetryItems();

            //await SyncAsync(); // offline sync
        }

        private async Task RefreshTelemetryItems()
        {
            MobileServiceInvalidOperationException exception = null;
            try
            {
                // This code refreshes the entries in the list view by querying the telemetry2 table.
                    telemetryItems = await telemetryTable
                    .Where (s=> s.Complete==false)
                    .ToCollectionAsync();
            }
            catch (MobileServiceInvalidOperationException e)
            {
                exception = e;
            }

            if (exception != null)
            {
                await new MessageDialog(exception.Message, "Error loading items").ShowAsync();
            }
            else
            {
                //Sort in descending order = Most recent first .. Ww want the latest value of each sensor
                var sortedTelemetryItems = telemetryItems
                    .OrderByDescending(telemetryItem => telemetryItem.Id);
                
                //Group by sensor name
                var orderGroups =
                    from p in sortedTelemetryItems 
                    group p by p.Sensor into g 
                    select new { Category = g.Key, Sensors = g };

                //Get only the first item in each group = Most Recent
                 List<Telemetry2> telemetryItemsListMostRecentInGroup = new List<Telemetry2>();
                 foreach (var key in orderGroups)
                 {
                     
                     telemetryItemsListMostRecentInGroup.Add(key.Sensors.First<Telemetry2>());
                     //Mark other vakues as complete. Embedded devices then can just get the "incomplete values".
                     for (int i=1;i<key.Sensors.Count();i++)
                    {
                        Telemetry2 t2i = key.Sensors.ElementAt<Telemetry2>(i);
                        t2i.Complete = true;
                        await telemetryTable.UpdateAsync(t2i);
                    }
                 }
 

                //Set as displayed list
                ListItems.ItemsSource = telemetryItemsListMostRecentInGroup.OrderBy(s=>s.Sensor); // telemetryItems;
                this.ButtonSave.IsEnabled = true;
            }
        }

        private async Task UpdateCheckedTelemetryItem(Telemetry2 item)
        {
            // This code takes a freshly completed TodoItem and updates the database. When the MobileService 
            // responds, the item is removed from the list 
            await telemetryTable.UpdateAsync(item);
            telemetryItems.Remove(item);
            ListItems.Focus(Windows.UI.Xaml.FocusState.Unfocused);

            //await SyncAsync(); // offline sync
        }

        private async void ButtonRefresh_Click(object sender, RoutedEventArgs e)
        {
            ButtonRefresh.IsEnabled = false;

            //await SyncAsync(); // offline sync
            await RefreshTelemetryItems();

            ButtonRefresh.IsEnabled = true;
        }

        //Clean up of Sensor names.
        private string Normalise(string strn)
        {
            string strnTemp ="";
            if (strn != "")
            {
            strnTemp = strn.Substring(1).ToLower();
            strnTemp = strn.ToUpper()[0].ToString() + strnTemp;
            }
            return strnTemp;
        }

        private async void ButtonSave_Click(object sender, RoutedEventArgs e)
        {
            ButtonSave.IsEnabled = false;
            //var telemetryItem = new Telemetry { Sensor = SensorInput.Text, Value = int.Parse(ValueInput.Text) };
            var telemetryItem = new Telemetry2 { Sensor = Normalise(SensorInput.Text) , Value = int.Parse(ValueInput.Text) , Complete =false};
            await InsertTelemetryItem(telemetryItem);
            ButtonSave.IsEnabled = true;
        }

        private async void CheckBoxComplete_Checked(object sender, RoutedEventArgs e)
        {
            CheckBox cb = (CheckBox)sender;
            Telemetry2 telemetryItem = cb.DataContext as Telemetry2;
            await UpdateCheckedTelemetryItem(telemetryItem);
        }

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            //await InitLocalStoreAsync(); // offline sync
            await RefreshTelemetryItems();
        }

        #region Offline sync

        //private async Task InitLocalStoreAsync()
        //{
        //    if (!App.MobileService.SyncContext.IsInitialized)
        //    {
        //        var store = new MobileServiceSQLiteStore("localstore.db");
        //        store.DefineTable<TodoItem>();
        //        await App.MobileService.SyncContext.InitializeAsync(store);
        //    }
        //
        //    await SyncAsync();
        //}

        //private async Task SyncAsync()
        //{
        //    await App.MobileService.SyncContext.PushAsync();
        //    await todoTable.PullAsync("todoItems", todoTable.CreateQuery());
        //}

        #endregion 
    }
}
